﻿using mozhi.smarterp.Business.Enums;
using Mozhi.Abp.Domain.AuthorCenter;
using Mozhi.Abp.Domain.BasicData;
using System;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp;

namespace mozhi.smarterp.Business
{
    public class DocumentAggregateRoot : AggregateRootBase
    {
        public string Number { get; protected set; }

        public DateTime Date { get; protected set; }

        public virtual bool IncludeTax { get; protected set; }

        public virtual Guid CurrencyId { get; protected set; }

        public virtual Currency Currency { get; protected set; }

        public virtual decimal ExchangeRate { get; protected set; }

        /// <summary>
        /// 总税额
        /// </summary>
        public virtual decimal? TaxAmountFr { get; protected set; }

        public virtual decimal? TaxAmount { get; protected set; }

        /// <summary>
        /// 总金额
        /// </summary>
        public virtual decimal AmountFr { get; protected set; }

        public virtual decimal Amount { get; protected set; }

        /// <summary>
        /// 价税合计金额
        /// </summary>
        public virtual decimal TotalAmountFr { get; protected set; }

        public virtual decimal TotalAmount { get; protected set; }

        public virtual string Comment { get; protected set; }

        /// <summary>
        /// 状态
        /// </summary>
        public virtual DocumentStatusType Status { get; protected set; }

        protected DocumentAggregateRoot() { }

        public DocumentAggregateRoot(Guid id, string number, DateTime date, bool includeTax, Currency currency, decimal exchangeRate, Department department, string comment) :
            base(id, department)
        {
            Number = number;
            Date = date;
            IncludeTax = includeTax;
            CurrencyId = currency == null ? default : currency.Id;
            Currency = currency;
            ExchangeRate = exchangeRate;
            Comment = comment;
            Status = DocumentStatusType.Creation;
        }

        public virtual void SetStatus(DocumentStatusType status)
        {
            if (Status == status)
                throw new UserFriendlyException("单据状态已更新，请刷新后查看", "100000");

            if (Status == DocumentStatusType.Approved && (status != DocumentStatusType.PendingApproval && status != DocumentStatusType.Closed))
                throw new UserFriendlyException("审核状态的单据只能反审核或者关闭" , "100000");

            if (Status == DocumentStatusType.Creation && (status != DocumentStatusType.PendingApproval && status != DocumentStatusType.Invalid))
                throw new UserFriendlyException("创建状态的单据只能提交或者作废", "100000");

            if(Status == DocumentStatusType.Invalid && status != DocumentStatusType.Creation)
                throw new UserFriendlyException("作废状态的单据只能先反作废", "100000");

            Status = status;
        }

        #region
        protected virtual void Validate()
        {
            if (Currency == null)
                throw new UserFriendlyException("货币不存在", "100000");

            Currency.Validate();

            if (Department != null)
                Department.Validate();

            Check.NotNull(Number, nameof(Number));
            Check.NotDefaultOrNull<DateTime>(Date, nameof(Date));
            Check.NotDefaultOrNull<Guid>(CurrencyId, nameof(CurrencyId));

            if (ExchangeRate <= 0)
                throw new UserFriendlyException("汇率必须大于0", "100000");
        }

        protected virtual void ValidateStatus()
        {
            if (Status == DocumentStatusType.PendingApproval)
                throw new UserFriendlyException($"单据：{Number}已提交，不允许进行修改", "100000");

            if (Status == DocumentStatusType.Approved)
                throw new UserFriendlyException($"单据：{Number}已审核，不允许进行修改", "100000");

            if (Status == DocumentStatusType.Invalid)
                throw new UserFriendlyException($"单据：{Number}已作废，不允许进行修改", "100000");

            if (Status == DocumentStatusType.Closed)
                throw new UserFriendlyException($"单据：{Number}已关闭，不允许进行修改", "100000");
        }

        
        #endregion
    }

    public class DocumentAggregateRoot<TItem> : DocumentAggregateRoot where TItem : DocumentEntity
    {
        public List<TItem> Items { get; protected set; }

        protected DocumentAggregateRoot() { }

        public DocumentAggregateRoot(Guid id, string number, DateTime date, bool includeTax, Currency currency, decimal exchangeRate, Department department, string comment)
            : base(id, number, date, includeTax, currency, exchangeRate, department, comment)
        {

        }

        public virtual void Change(string number, DateTime date, bool includeTax, Currency currency, decimal exchangeRate, Department department, string comment)
        {
            Number = number;
            Date = date;
            IncludeTax = includeTax;
            Currency = currency;
            CurrencyId = currency == null ? default : currency.Id;
            ExchangeRate = exchangeRate;
            Department = department;
            DepartmentId = department == null ? default : department.Id;
            Comment = comment;
        }

        public virtual void ChangeItems(List<TItem> items)
        {
            if (Status == DocumentStatusType.Approved)
                throw new UserFriendlyException("报价单已经审核，不允许修改", "100000");

            if (items == null || items.Count == 0)
                throw new UserFriendlyException("至少需要一行明细", "100000");

            items.ForEach(x =>
            {
                AddOrUpdateItem(x);
            });

            //删除掉不存在的分录
            var itemIds = items.Select(item => item.Id).ToList();

            var deleted = Items.Where(x => !itemIds.Contains(x.Id)).ToList();

            deleted.ForEach(x => Items.Remove(x));

            //计算总金额
            CalculateTotalAmount();

            //重新排序
            int index = 0;
            Items.ToList().ForEach(x => x.ChangeIndex(index++));

            ValidateItems();
        }

        #region

        protected virtual void AddOrUpdateItem(TItem item)
        {
            throw new NotImplementedException();
        }

        protected virtual void CalculateTotalAmount()
        {
            if (Items.Count == 0)
                return;

            TotalAmount = Items.Sum(x => x.TotalAmount);
            TotalAmountFr = Items.Sum(x => x.TotalAmountFr);

            Amount = Items.Sum(x => x.Amount);
            AmountFr = Items.Sum(x => x.AmountFr);

            TaxAmount = Items.Sum(x => x.TaxAmount);
            TaxAmountFr = Items.Sum(x => x.TaxAmountFr);
        }

        protected void ValidateItems()
        {
            if (Items == null || Items.Count == 0)
                throw new UserFriendlyException("单据分录不能为空", "100000");
        }
        #endregion
    }
}
